#import "BWStitchInspectorPane.h"
#import "BWBorkStitchDocument.h"
#import "BWDocumentUndo.h"
#import "BWStitch.h"
#import "BWStitchView.h"
#import "BWStitchSelection.h"
#import "BWStitchArray.h"
#import "BWConfigPopUpButton.h"
#import "BWConfigTemplate.h"

@implementation BWStitchInspectorPane

- (id) init
{
    if (self = [super init]) {
        if (![NSBundle loadNibNamed: @"BWStitchInspectorPane"
                       owner: self]) {
            NSLog (@"could not load BWStitchInspectorPane.nib");
        }

        NSNotificationCenter *center;
        center = [NSNotificationCenter defaultCenter];

        [center addObserver: self
                selector: @selector(stitchSelectionChangeNotification:)
                name: BWBorkStitchDocument_StitchSelectionChangeNotification
                object: nil];

        [center addObserver: self
                selector: @selector(stitchBendNotification:)
                name: BWStitchView_StitchBendNotification
                object: nil];
    }

    return (self);

} // init


- (NSImage *) toolbarIcon
{
    NSImage *image;
    image = [NSImage imageNamed: @"stitch-pane.tiff"];

    return (image);

} // toolbarIcon


// --------------------------------------------------
// UI foobage


// !!! this average idea is kind of cheesy - is there a better way?

- (float) averageWidthForSelectedStitches
{
    float sum = 0.0;

    NSEnumerator *enumerator;
    enumerator = [[document selectedStitches] objectEnumerator];

    BWStitch *stitch;
    while (stitch = [enumerator nextObject]) {
        float width;
        width = [stitch width];
        sum += width;
    }

    float average;
    average = sum / [[document selectedStitches] count];

    return (average);
    
} // averageWidthForSelectedStitches


- (void) getAverageBendFactor: (float *) bendFactor
                 displacement: (float *) displacement
                     flatness: (float *) flatness
{
    *bendFactor = *displacement = *flatness = 0.0;
    float count = [[document selectedStitches] count];

    NSEnumerator *enumerator;
    enumerator = [[document selectedStitches] objectEnumerator];

    BWStitch *stitch;
    while (stitch = [enumerator nextObject]) {
        *bendFactor += [stitch bendFactor];
        *displacement += [stitch bendDisplacement];
        *flatness += [stitch bendFlatness];
    }
    
    if (count > 0.0) {
        *bendFactor /= count;
        *displacement /= count;
        *flatness /= count;
    }
    
} // getAverageBendFactor


- (NSColor *) firstStitchColorForSelectedStitches
{
    NSColor *color = nil;

    NSEnumerator *enumerator;
    enumerator = [[document selectedStitches] objectEnumerator];

    BWStitch *stitch;
    while (stitch = [enumerator nextObject]) {
        color = [stitch fillColor];
        if (color != nil) {
            break;
        }
    }

    return (color);

} // firstStitchColorForSelectedStitches

- (void) getArrowState: (NSCellStateValue *) state
            firstColor: (NSColor **) color
         averageLength: (float *) length
         averageWeight: (float *) weight
{
    *state = NSOffState; // Mixed / Off / On
    *color = nil;
    *length = *weight = 0.0;

    NSEnumerator *enumerator;
    enumerator = [[document selectedStitches] objectEnumerator];

    int arrowOnCount, arrowOffCount;
    arrowOnCount = arrowOffCount = 0;

    BWStitch *stitch;
    while (stitch = [enumerator nextObject]) {
        BWStitch_ArrowKind kind;
        kind = [stitch arrow];

        if (kind == BWStitch_NoArrow) {
            arrowOffCount++;
        } else {
            arrowOnCount++;
        }

        *length += [stitch arrowLength];
        *weight += [stitch arrowWeight];

        if (*color == nil) {
            NSColor *arrowColor = [stitch arrowColor];
            if (arrowColor != nil) {
                *color = arrowColor;
            }
        }
    }

    *length /= [[document selectedStitches] count];
    *weight /= [[document selectedStitches] count];

    if (arrowOffCount != 0 && arrowOnCount != 0) {
        *state = NSMixedState;
    } else if (arrowOffCount != 0) {
        *state = NSOffState;
    } else {
        *state = NSOnState;
    }
 
} // getArrowState


- (void) updateUI
{
    if (document == nil) {
        return;
    }

    [stitchWidthSlider setFloatValue: [self averageWidthForSelectedStitches]];

    NSColor *fillColor = [self firstStitchColorForSelectedStitches];

    if (fillColor != nil) {
        [stitchColorWell setColor: fillColor];
    }

    float bendFactor, displacement, flatness;
    [self getAverageBendFactor: &bendFactor
          displacement: &displacement
          flatness: &flatness];

    [stitchBendFactorSlider setFloatValue: bendFactor];
    [stitchBendDisplaceSlider setFloatValue: displacement];
    [stitchBendFlatnessSlider setFloatValue: flatness];

    NSCellStateValue state;
    NSColor *arrowColor;
    float arrowLength, arrowWeight;

    [self getArrowState: &state
          firstColor: &arrowColor
          averageLength: &arrowLength
          averageWeight: &arrowWeight];

    [showArrowCheckbox setState: state];
    if (arrowColor != nil) {
        [arrowColorColorWell setColor: arrowColor];
    }

    [arrowLengthSlider setFloatValue: arrowLength];
    [arrowWeightSlider setFloatValue: arrowWeight];

} // updateUI



- (IBAction) stitchSetWidth: (id) sender
{
    float width;
    width = [sender floatValue];

    NSIndexSet *indexes;
    indexes = [[document selectedStitches] indexesForSelection];
    
    [document changeWidth: width  
              forIndexes: indexes];

} // stitchSetWidth


- (IBAction) stitchSetColor: (id) sender
{
    NSColor *color;
    color = [sender color];

    NSIndexSet *indexes;
    indexes = [[document selectedStitches] indexesForSelection];

    [document changeFillColor: color  
              forIndexes: indexes];

} // stitchSetColor


- (IBAction) stitchSetBendFactor: (id) sender
{
    float bendFactor;
    bendFactor = [sender floatValue];

    NSIndexSet *indexes;
    indexes = [[document selectedStitches] indexesForSelection];

    [document changeBendFactor: bendFactor  
              forIndexes: indexes];
    
} // stitchSetBendFactor


- (IBAction) stitchSetBendDisplace: (id) sender
{
    float bendDisplace;
    bendDisplace = [sender floatValue];

    NSIndexSet *indexes;
    indexes = [[document selectedStitches] indexesForSelection];

    [document changeBendDisplacement: bendDisplace
              forIndexes: indexes];

} // stitchSetBendDisplace


- (IBAction) stitchSetBendFlatness: (id) sender
{
    float bendFlatness;
    bendFlatness = [sender floatValue];

    NSIndexSet *indexes;
    indexes = [[document selectedStitches] indexesForSelection];

    [document changeBendFlatness: bendFlatness
              forIndexes: indexes];
    
} // stitchSetBendFlatness


- (IBAction) stitchToggleArrow: (id) sender
{
    NSIndexSet *indexes;
    indexes = [[document selectedStitches] indexesForSelection];

    if ([sender state] == NSOnState || [sender state] == NSMixedState) {
        [document setArrow: BWStitch_Arrow
                  forIndexes: indexes];
    } else {
        [document setArrow: BWStitch_NoArrow
                  forIndexes: indexes];
    }

} // stitchToggleArrow


- (IBAction) stitchSetArrowColor: (id) sender
{
    NSColor *color;
    color = [sender color];

    NSIndexSet *indexes;
    indexes = [[document selectedStitches] indexesForSelection];
    
    [document changeArrowColor: color 
              forIndexes: indexes];

} // stitchSetArrowColor


- (IBAction) stitchSetArrowLength: (id) sender
{
    float value;
    value = [sender floatValue];

    NSIndexSet *indexes;
    indexes = [[document selectedStitches] indexesForSelection];
    
    [document changeArrowLength: value
              forIndexes: indexes];

} // stitchSetArrowLength


- (IBAction) stitchSetArrowWeight: (id) sender
{
    float value;
    value = [sender floatValue];

    NSIndexSet *indexes;
    indexes = [[document selectedStitches] indexesForSelection];
    
    [document changeArrowWeight: value
              forIndexes: indexes];

} // stitchSetArrowWeight


- (IBAction) stitchApplyToAllStitches: (id) sender
{
    BWStitch *targetStitch = [document targetStitch];

    NSEnumerator *enumerator;
    enumerator = [[document stitches] objectEnumerator];

    BWStitch *stitch;
    while (stitch = [enumerator nextObject]) {
        [stitch setFillColor: [targetStitch fillColor]];
        [stitch setWidth: [targetStitch width]];
    }

    [document setNeedsDisplay: YES];
    [document updateChangeCount: NSChangeDone];

} // stitchApplyToAllStitches


- (IBAction) stitchUseForNewDocuments: (id) sender
{
    [document setNeedsDisplay: YES];
    [document updateChangeCount: NSChangeDone];

} // stitchUseForNewDocuments


- (IBAction) stitchToggleUseForNewStitches: (id) sender
{
    [document setNeedsDisplay: YES];
    [document updateChangeCount: NSChangeDone];

} // stitchToggleUseForNewStitches


- (IBAction) stitchZeroBendFactor: (id) sender
{
    NSIndexSet *indexes;
    indexes = [[document selectedStitches] indexesForSelection];

    [document changeBendFactor: 0.0
              forIndexes: indexes];
    [self updateUI];
    
} // stitchZeroBendFactor


- (IBAction) stitchZeroBendDisplace: (id) sender
{
    NSIndexSet *indexes;
    indexes = [[document selectedStitches] indexesForSelection];

    [document changeBendDisplacement: 0.0
              forIndexes: indexes];
    [self updateUI];

} // stitchZeroBendDisplace


- (IBAction) stitchZeroBendFlatness: (id) sender
{
    NSIndexSet *indexes;
    indexes = [[document selectedStitches] indexesForSelection];

    [document changeBendFlatness: 0.0
              forIndexes: indexes];
    [self updateUI];

} // stitchZeroBendFlatness


- (void) applyWidthAttributeToStitch: (BWStitch *) stitch
{
    [stitch setWidth: [stitchWidthSlider floatValue]];
    [stitch setFillColor: [stitchColorWell color]];

} // applyWidthAttributeToStitch



- (void) applyAttributesToStitch: (BWStitch *) stitch
{
    [stitch setWidth: [stitchWidthSlider floatValue]];
    [stitch setFillColor: [stitchColorWell color]];
    [stitch setBendFactor: [stitchBendFactorSlider floatValue]];
    [stitch setBendDisplacement: [stitchBendDisplaceSlider floatValue]];
    [stitch setBendFlatness: [stitchBendFlatnessSlider floatValue]];

    if ([showArrowCheckbox state] == NSOnState) {
        [stitch setArrow: BWStitch_Arrow];
    } else {
        [stitch setArrow: BWStitch_NoArrow];
    }

    [stitch setArrowLength: [arrowLengthSlider floatValue]];
    [stitch setArrowWeight: [arrowWeightSlider floatValue]];
    [stitch setArrowColor: [arrowColorColorWell color]];
    
} // applyAttributesToStitch


- (IBAction) stitchApplyWidthAttributeToAll: (id) sender
{
    NSEnumerator *enumerator;
    enumerator = [[document stitches] objectEnumerator];

    BWStitch *stitch;
    while (stitch = [enumerator nextObject]) {
        [self applyWidthAttributeToStitch: stitch];
    }
    [self applyWidthAttributeToStitch: [document templateStitch]];

    [document setNeedsDisplay: YES];
    [document updateChangeCount: NSChangeDone];

} // stitchApplyWidthAttributeToAll


- (IBAction) stitchApplyStitchAttributesToAll: (id) sender
{
    NSEnumerator *enumerator;
    enumerator = [[document stitches] objectEnumerator];

    BWStitch *stitch;
    while (stitch = [enumerator nextObject]) {
        [self applyAttributesToStitch: stitch];
    }
    [self applyAttributesToStitch: [document templateStitch]];

    [document setNeedsDisplay: YES];
    [document updateChangeCount: NSChangeDone];

} // stitchApplyStitchAttributesToAll



- (void) stitchSelectionChangeNotification: (NSNotification *) notification
{
    [self updateUI];

} // stitchSelcetionChangeNotification


- (void) stitchBendNotification: (NSNotification *) notification
{
    [self updateUI];

} // stitchSelcetionChangeNotification



- (NSString *) paneName
{
    return (@"BWStitchInspectorPane");
} // name


// --------------------------------------------------
// config pop up button delegate methods

- (NSString *) nameForConfigPopUpButton: (BWConfigPopUpButton *) button
{
    return (@"Stitch Templates...");

} // nameForConfigPopUpButton


- (NSString *) categoryNameForPopUpButton: (BWConfigPopUpButton *) button
{
    return (@"Stitch Templates");
} // categoryNameForPopu


- (NSWindow *) windowForConfigSheetForPopUpButton: (BWConfigPopUpButton *) button
{
    return ([paneView window]);

} // windowForConfigSheetForPopUpButtonAndBoytIsThisNameEntirelyTooLong


- (void) populateTemplate: (BWConfigTemplate *) template
           forPopUpButton: (BWConfigPopUpButton *) button
{
    float stitchWidth = [self averageWidthForSelectedStitches];
    NSColor *fillColor = [self firstStitchColorForSelectedStitches];
    float bendFactor, displacement, flatness;
    [self getAverageBendFactor: &bendFactor
          displacement: &displacement
          flatness: &flatness];
    
    NSCellStateValue state;
    NSColor *arrowColor;
    float arrowLength, arrowWeight;
    [self getArrowState: &state
          firstColor: &arrowColor
          averageLength: &arrowLength
          averageWeight: &arrowWeight];

    [template setFloatValue: stitchWidth
              forKey: @"Stitch Width"];
    [template setObjectValue: fillColor
              forKey: @"Fill Color"];
    [template setFloatValue: bendFactor
                  forKey: @""];
    [template setFloatValue: displacement
                  forKey: @""];
    [template setFloatValue: flatness
                  forKey: @""];
    [template setIntValue: state
              forKey: @""];
    [template setObjectValue: arrowColor
              forKey: @""];
    [template setFloatValue: arrowLength
                  forKey: @""];
    [template setFloatValue: arrowWeight
                  forKey: @""];
    
} // populateTemplateForPopUpButton


- (void) useTemplate: (BWConfigTemplate *) template
     fromPopUpButton: (BWConfigPopUpButton *) button
{
    
} // useTemplate



@end // BWStitchInspectorPane

